﻿'*******************************************************************************************
'* Copyright Brügmann Software GmbH, Papenburg
'* Author: Björn Kremer
'* Contact: codeplex<at>patorg.de
'* 
'* VB.CMIS is a VB.NET implementation of the Content Management Interoperability Services (CMIS) standard
'*
'* This file is part of VB.CMIS.
'* 
'* VB.CMIS is free software: you can redistribute it and/or modify
'* it under the terms of the GNU Lesser General Public License as published by
'* the Free Software Foundation, either version 3 of the License, or
'* (at your option) any later version.
'* 
'* VB.CMIS is distributed in the hope that it will be useful,
'* but WITHOUT ANY WARRANTY; without even the implied warranty of
'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'* GNU Lesser General Public License for more details.
'* 
'* You should have received a copy of the GNU Lesser General Public License
'* along with VB.CMIS. If not, see <http://www.gnu.org/licenses/>.
'*******************************************************************************************
Imports System.ServiceModel
Imports System.ServiceModel.Description

Public Class ServiceManager
   Implements IDisposable
   Private _host As New List(Of ServiceHost)

   Private _lock As New Object
   ''' <summary>
   ''' Starts a new selfhosted WCF Service
   ''' </summary>
   ''' <param name="baseAddressHttp"></param>
   ''' <param name="baseAddressHttps"></param>
   ''' <remarks></remarks>
   Public Sub OpenHost(baseAddressHttp As Uri, baseAddressHttps As Uri)
      SyncLock _lock
         'Warmup Common class
         Dim dummy As Boolean = Common.EnableLogin
         For Each h As ServiceHost In _host
            h.Close()
         Next
         _host.Clear()
       
         'Create an instance of the data provider: Warmup + Testing
         Dim provider As Object = New ProviderManager().Provider

         Dim param As New OpenHostParameter
         param.BaseAddress = baseAddressHttp
         param.Mode = WebHttpSecurityMode.TransportCredentialOnly

         'Start Service in a different thread.
         StartThread(param)
         If baseAddressHttps IsNot Nothing Then
            param = New OpenHostParameter
            param.BaseAddress = baseAddressHttps
            param.Mode = WebHttpSecurityMode.Transport
            StartThread(param)
         End If
      End SyncLock
   End Sub
   Private Sub StartThread(param As OpenHostParameter)
      Dim th As New System.Threading.Thread(New Threading.ParameterizedThreadStart(AddressOf InnerOpenHost))
      th.Start(param)
      While th.IsAlive
         System.Threading.Thread.Sleep(1)
      End While
      If param.ReturnErrorObject IsNot Nothing Then
         Throw param.ReturnErrorObject
      End If
   End Sub
   Private Const MaxReceivedMessageSize As Integer = 52428800
   Private Sub InnerOpenHost(param As Object)
      Dim typedParam As OpenHostParameter = DirectCast(param, OpenHostParameter)
      Try
         Dim serviceHost As New System.ServiceModel.Web.WebServiceHost(GetType(Services.Service), {typedParam.BaseAddress})

         Dim binding As New System.ServiceModel.WebHttpBinding
         binding.Security.Mode = typedParam.Mode
         If Common.EnableLogin Then
            binding.Security.Transport.ClientCredentialType = ServiceModel.HttpClientCredentialType.Basic
         Else
            binding.Security.Transport.ClientCredentialType = ServiceModel.HttpClientCredentialType.None
         End If

         binding.TransferMode = TransferMode.Streamed
         binding.AllowCookies = True
         binding.MaxReceivedMessageSize = MaxReceivedMessageSize
         Dim ep As System.ServiceModel.Description.ServiceEndpoint = serviceHost.AddServiceEndpoint(GetType(Services.Interfaces.ICMISMainService), binding, "")
         ep.Behaviors.Add(New System.ServiceModel.Description.WebHttpBehavior With {.HelpEnabled = True})

         Dim debugBehavior As System.ServiceModel.Description.ServiceDebugBehavior = serviceHost.Description.Behaviors.Find(Of System.ServiceModel.Description.ServiceDebugBehavior)()
         If debugBehavior Is Nothing Then
            debugBehavior = New System.ServiceModel.Description.ServiceDebugBehavior
            serviceHost.Description.Behaviors.Add(debugBehavior)
         End If
         debugBehavior.IncludeExceptionDetailInFaults = Common.Debug

         serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = New Services.WCFHelper.CustomUsernamePasswordValidator
         serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = Security.UserNamePasswordValidationMode.Custom
         serviceHost.Open()
         _host.Add(serviceHost)
      Catch ex As Exception
         typedParam.ReturnErrorObject = ex
      End Try
   End Sub


   

   Private Class OpenHostParameter
      Public Property BaseAddress As Uri
      Public Property Mode As System.ServiceModel.WebHttpSecurityMode
      Public Property ReturnErrorObject As Exception
   End Class

#Region "IDisposable Support"
   Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe

   ' IDisposable
   Protected Overridable Sub Dispose(disposing As Boolean)
      If Not Me.disposedValue Then
         If disposing Then
           For Each h As ServiceHost In _host
               h.Close()
            Next
            _host.Clear()
         End If

      End If
      Me.disposedValue = True
   End Sub

   '  Finalize() nur überschreiben, wenn Dispose(ByVal disposing As Boolean) oben über Code zum Freigeben von nicht verwalteten Ressourcen verfügt.
   'Protected Overrides Sub Finalize()
   '    ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
   '    Dispose(False)
   '    MyBase.Finalize()
   'End Sub

   ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
   Public Sub Dispose() Implements IDisposable.Dispose
      ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
      Dispose(True)
      GC.SuppressFinalize(Me)
   End Sub
#End Region

End Class
